home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 1992 August / info-mac-1992.iso / UNIX / Unsit 1.5.shar < prev    next >
Internet Message Format  |  1992-08-29  |  40KB

  1. Date: Mon, 29 Jan 90 01:32:06 EST
  2. From: jjw7384@ultb.isc.rit.edu (Jeff Wasilko)
  3. Subject: Batch Unbinhexing/Unstuffing (SUMMARY and SOURCE)
  4.  
  5.  
  6. Quite a while ago, I requested info on batch un-binhexing/
  7. un-stufing software available for the mac. I received a few
  8. replies about this, all of them but one suggesting a solution
  9. centered around a mainframe. One person suggested that Ray Lau's 
  10. commercial version of Stuffit might do batch work.
  11.  
  12. What I found was a trio of programs from the archives at
  13. sumex-aim.stanford.edu in the /info-mac/unix directory. The
  14. combination of these three programs allow almost-batch operation
  15. (I'll get into why it's 'almost' later).
  16.  
  17. The three programs are:
  18. -rw-r--r--  1 macmod   info-mac    54554 Jan 16 18:18 mcvert-15.shar
  19.  
  20.     mcvert converts a .hqx (BinHex 4.0) file to a .bin (MacBinary
  21.     file) that can be read by unsit. This program allows wildcard
  22.     operations. Additionally, mcvert will unpack PackIt files.
  23.  
  24.     Files in: *.hqx
  25.     Files out: *.bin (generally *.sit.bin)
  26.  
  27. -rw-r--r--  1 macmod   info-mac    26067 Jan  1  1989 unsit.shar
  28.  
  29.     unsit will decompress .sit.bin (MacBinary Stuffit files)
  30.  
  31.     I am enclosing a new version of unsit that Allen sent me to
  32.     allow input from MacBinary files. Previously, it was only
  33.     possible to input from macput/macget formatted files. The new version
  34.     also adds compatiblity with Stuffit 1.5.1 and the new HMF
  35.     folder scheme.
  36.  
  37.     At present, unsit can only output files in macput/macget format,
  38.     but the author Allan Weber (weber%brand.usc.edu@oberon.usc.edu)
  39.     said that he may add the option to output directly to MacBinary format.
  40.  
  41.     Files in: *.sit.bin 
  42.     Files out: foo.rsrc, foo.data, foo.info 
  43.                        
  44. -rw-r--r--  1 macmod   info-mac     4184 Jan  1  1989 macbinary.shar
  45.  
  46.     macbinary (macbin) converts macput/macget type files to
  47.     MacBinary files. This allows easy downloading with progams
  48.     such as Kermit or ZTerm.
  49.  
  50.     macbin does NOT support wildcards, so this part of the
  51.     conversion must be done manually.
  52.  
  53.     Files in: foo.rsrc, foo.data, foo.info
  54.     Files out: foo.bin (Unstuffed and in Binary format)
  55.  
  56.  
  57. The combination of programs works very well and is extremely fast
  58. on our vax, especially when comparied to Stuffit's performance on
  59. a Plus.
  60.  
  61. Since this process requires the use of three different programs,
  62. I'm writing a shell script to tie everything together. When I get
  63. it running, I'll send it along too.
  64.  
  65. I'm including a new version of unsit that reads macbinary files.
  66.  
  67. Jeff
  68.  
  69.  
  70. | RIT VAX/VMS Systems: |     Jeff Wasilko     |     RIT Ultrix Systems:     |
  71. |BITNET: jjw7384@ritvax+----------------------+INET:jjw7384@ultb.isc.rit.edu|
  72. |UUCP: {psuvax1, mcvax}!ritvax.bitnet!JJW7384 +___UUCP:jjw7384@ultb.UUCP____+
  73. |INTERNET: jjw7384@isc.rit.edu                |'claimer: No one cares.      |
  74.  
  75.  
  76. ------cut here for source for unsit 1.5------
  77.  
  78.  
  79. >From weber%brand.usc.edu%oberon.USC.EDU@usc.edu Wed Jan 10 17:35:07 1990
  80. Received: by ultb.isc.rit.edu (5.57/5.2 (Postmaster DPMSYS))
  81.     id AA28138; Wed, 10 Jan 90 17:34:45 EST
  82. Received: from brand.usc.edu by usc.edu (5.59/SMI-3.0DEV3) id AA26388; 
  83.                 Wed, 10 Jan 90 14:34:03 PST
  84. Received: by brand (5.61/SMI-3.0DEV3) id AA08278; 
  85.                 Wed, 10 Jan 90 14:33:20 -0800
  86. Date: Wed, 10 Jan 1990 14:33:17 PST
  87. >From: Allan G. Weber <weber%brand.usc.edu@usc.edu>
  88. >To: jjw7384@usc.edu (Jeff Wasilko)
  89. In-Reply-To: Your message of Wed, 10 Jan 90 16:32:38 EST 
  90. >Subject: unsit
  91. Message-Id: <CMM.0.88.632010797.weber@brand.usc.edu>
  92. Status: RO
  93.  
  94. The problem is probably that unsit is expecting the file to be just the
  95. data fork of the Mac file, and Macbinary format has the data and resource
  96. forks together along with a header.  I've include the lastest version of
  97. unsit below in case you don't have it.  Some time ago I added a option to
  98. the program to make it skip the Macbinary header by using a "-m" switch
  99. on the command line.  Try the version below with the -m and hopefully it
  100. will work.
  101.  
  102. Allan Weber
  103.  
  104. #! /bin/sh
  105. # This is a shell archive, meaning:
  106. # 1. Remove everything above the #! /bin/sh line.
  107. # 2. Save the resulting text in a file.
  108. # 3. Execute the file with /bin/sh (not csh) to create the files:
  109. #    README
  110. #    Makefile
  111. #    unsit.c
  112. #    stuffit.h
  113. #    updcrc.c
  114. #    getopt.c
  115. #    unsit.1
  116. # This archive created: Wed Jan 10 14:25:12 1990
  117. export PATH; PATH=/bin:$PATH
  118. if test -f 'README'
  119. then
  120.     echo shar: will not over-write existing file "'README'"
  121. else
  122. cat << \SHAR_EOF > 'README'
  123.               Unsit, version 1.5
  124.  
  125. These are the souces for "unsit", a Unix program for breaking apart
  126. StuffIt archive files created on a Macintosh into separate files on
  127. the Unix system.  See the documentation at the beginning of "unsit.c"
  128. or the man page "unsit.1" for more information.
  129.  
  130. To build the program, compile unsit.c and updcrc.c and link together.
  131. If your system doesn't have the getopt() routine in its standard
  132. library, also compile getopt.c and include it in the link.
  133.  
  134. This program opens a pipe to the "compress" program for doing the
  135. uncompression of some of the files in the archive.  Most Unix sites
  136. probably already have "compress".  If not, it can be found in the
  137. comp.sources.unix archives.
  138.  
  139. Comments and bug reports should be send to weber%brand.usc.edu@oberon.usc.edu
  140.  
  141.  
  142.                 Allan G. Weber
  143.                 Signal and Image Processing Institute
  144.                 University of Southern California
  145.                 Powell Hall 306, MC-0272
  146.                 Los Angeles, CA 90089-0272
  147.                 (213) 743-5519
  148. SHAR_EOF
  149. fi # end of overwriting check
  150. if test -f 'Makefile'
  151. then
  152.     echo shar: will not over-write existing file "'Makefile'"
  153. else
  154. cat << \SHAR_EOF > 'Makefile'
  155. GETOPT = 
  156. #GETOPT = getopt.o
  157.  
  158. unsit : unsit.o updcrc.o $(GETOPT)
  159.     cc -o unsit unsit.o updcrc.o $(GETOPT)
  160.  
  161. unsit.o : unsit.c stuffit.h
  162. getopt.o : getopt.c
  163.  
  164. unsit.shar : README Makefile unsit.c stuffit.h updcrc.c getopt.c unsit.1
  165.     shar README Makefile unsit.c stuffit.h updcrc.c getopt.c unsit.1 \
  166.     >unsit.shar
  167. SHAR_EOF
  168. fi # end of overwriting check
  169. if test -f 'unsit.c'
  170. then
  171.     echo shar: will not over-write existing file "'unsit.c'"
  172. else
  173. cat << \SHAR_EOF > 'unsit.c'
  174. /*
  175.            unsit - Macintosh StuffIt file extractor
  176.  
  177.              Version 1.5c, for StuffIt 1.5
  178.  
  179.                 August 3, 1989
  180.  
  181. This program will unpack a Macintosh StuffIt file into separate files.
  182. The data fork of a StuffIt file contains both the data and resource
  183. forks of the packed files.  The program will unpack each Mac file into
  184. separate .data, .rsrc., and .info files that can be downloaded to a
  185. Mac using macput.  The program is much like the "unpit" program for
  186. breaking apart Packit archive files.
  187.  
  188.             ***** IMPORTANT *****
  189. To extract StuffIt files that have been compressed with the Lempel-Ziv
  190. compression method, unsit pipes the data through the "compress"
  191. program with the appropriate switches, rather than incorporate the
  192. uncompression routines within "unsit".  Therefore, it is necessary to
  193. have the "compress" program on the system and in the search path to
  194. make "unsit" work.  "Compress" is available from the comp.sources.unix
  195. archives.
  196.  
  197. The program syntax is much like unpit and macput/macget, with some added
  198. options:
  199.  
  200.     unsit [-rdulvqfm] stuffit-file.data
  201.  
  202. The -r and -d flags will cause only the resource and data forks to be
  203. written.  The -u flag will cause only the data fork to be written and
  204. to have carriage return characters changed to Unix newline characters.
  205. The -l flag will make the program only list the files in the StuffIt
  206. file.  The -v flag causes the program to list the names, sizes, type,
  207. and creators of the files it is writing.  The -q flag causes it to
  208. list the name, type and size of each file and wait for a 'y' or 'n'
  209. for either writing that file or skipping it, respectively.  The -m
  210. flag is used when the input file in in the MacBinary format instead of
  211. three separate .data, .info, and .rsrc files.  It causes the program
  212. to skip the 128 byte MacBinary header before looking for the StuffIt
  213. header.
  214.  
  215. Version 1.5 of the unsit supports extracting files and folders as
  216. implemented by StuffIt 1.5's "Hierarchy Maintained Folder" feature.
  217. Each folder is extracted as a subdirectory on the Unix system with the
  218. files in the folder placed in the corresponding subdirectory.  The -f
  219. option can be used to "flatten" out the hierarchy and unsit will store
  220. all the files in the current directory.  If the query option (-q) is
  221. used and a "n" response is given to a folder name, none of the files
  222. or folders in that folder will be extraced.
  223.  
  224. Some of the program is borrowed from the macput.c/macget.c programs.
  225. Many, many thanks to Raymond Lau, the author of StuffIt, for including
  226. information on the format of the StuffIt archives in the
  227. documentation.  Several changes and enhancements supplied by David
  228. Shanks (cde@atelabs.UUCP) have been incorporated into the program for
  229. doing things like supporting System V and recognizing MacBinary files.
  230. I'm always glad to receive advice, suggestions, or comments about the
  231. program so feel free to send whatever you think would be helpful
  232.  
  233.  
  234.     Author: Allan G. Weber
  235.         weber%brand.usc.edu@oberon.usc.edu
  236.         ...sdcrdcf!usc-oberon!brand!weber
  237.     Date:   April 3, 1989
  238.  
  239. */
  240.  
  241. #include <stdio.h>
  242. #include <sys/types.h>
  243. #include <sys/stat.h>
  244.  
  245. typedef long OSType;
  246.  
  247. #include "stuffit.h"
  248.  
  249. /*
  250.  * Define the following if your Unix can only handle 14 character file names
  251.  * (e.g. Version 7 and System V).
  252.  */
  253. /* #define SHORTNAMES */
  254.  
  255. /*
  256.  * The following defines the name of the compress program that is used for the
  257.  * uncompression of Lempel-Ziv compressed files.  If the path is set up to
  258.  * include the right directory, this should work.
  259.  */
  260. #define COMPRESS   "compress"
  261.  
  262. #define IOBUFSIZ   4096
  263.  
  264. #define MACBINHDRSIZE  128L
  265.  
  266. #define INIT_CRC 0L
  267. extern unsigned short updcrc();
  268.  
  269. #define INFOBYTES 128
  270.  
  271. #define BYTEMASK 0xff
  272.  
  273. #define S_SIGNATURE    0
  274. #define S_NUMFILES     4
  275. #define S_ARCLENGTH    6
  276. #define S_SIGNATURE2  10
  277. #define    S_VERSION     14
  278. #define SITHDRSIZE    22
  279.  
  280. #define F_COMPRMETHOD    0
  281. #define F_COMPDMETHOD    1
  282. #define F_FNAME          2
  283. #define F_FTYPE         66
  284. #define F_CREATOR       70
  285. #define F_FNDRFLAGS     74
  286. #define F_CREATIONDATE  76
  287. #define F_MODDATE       80
  288. #define F_RSRCLENGTH    84
  289. #define F_DATALENGTH    88
  290. #define F_COMPRLENGTH   92
  291. #define F_COMPDLENGTH   96
  292. #define F_RSRCCRC      100
  293. #define F_DATACRC      102
  294. #define F_HDRCRC       110
  295. #define FILEHDRSIZE    112
  296.  
  297. #define F_NAMELEN 63
  298. #ifdef SHORTNAMES        /* short file names */
  299. # define I_NAMELEN 15        /* 14 char file names + '\0' terminator */
  300. #else
  301. # define I_NAMELEN 69        /* 63 + strlen(".info") + 1 */
  302. #endif
  303.  
  304. /* The following are copied out of macput.c/macget.c */
  305. #define I_NAMEOFF 1
  306. /* 65 <-> 80 is the FInfo structure */
  307. #define I_TYPEOFF 65
  308. #define I_AUTHOFF 69
  309. #define I_FLAGOFF 73
  310. #define I_LOCKOFF 81
  311. #define I_DLENOFF 83
  312. #define I_RLENOFF 87
  313. #define I_CTIMOFF 91
  314. #define I_MTIMOFF 95
  315.  
  316. #define INITED_BUG
  317. #define INITED_OFF    I_FLAGOFF    /* offset to byte with Inited flag */
  318. #define INITED_MASK    (~1)        /* mask to '&' with byte to reset it */
  319.  
  320. #define TEXT 0
  321. #define DATA 1
  322. #define RSRC 2
  323. #define FULL 3
  324. #define DUMP 4
  325.  
  326. #define NODECODE 0
  327. #define DECODE   1
  328.  
  329. #define H_ERROR -1
  330. #define H_EOF    0
  331. #define H_WRITE  1
  332. #define H_SKIP   2
  333.  
  334. struct node {
  335.     int flag, byte;
  336.     struct node *one, *zero;
  337. } nodelist[512], *nodeptr, *read_tree();    /* 512 should be big enough */
  338.  
  339. struct sitHdr sithdr;
  340.  
  341. char f_info[I_NAMELEN];
  342. char f_data[I_NAMELEN];
  343. char f_rsrc[I_NAMELEN];
  344.  
  345. char info[INFOBYTES];
  346. char mname[F_NAMELEN+1];
  347. char uname[F_NAMELEN+1];
  348. char iobuf[IOBUFSIZ];
  349.  
  350. int mode, txtmode, listonly, verbose, query, flatten;
  351. int bit, chkcrc, numfiles, depth;
  352. FILE *infp;
  353.  
  354. long get4();
  355. short get2();
  356. unsigned short write_file();
  357.  
  358. main(argc, argv)
  359. int argc;
  360. char *argv[];
  361. {
  362.     int status;
  363.     int c;
  364.     extern int optind;
  365.     extern char *optarg;
  366.     int errflg;
  367.     int macbin;
  368.  
  369.     mode = FULL;
  370.     errflg = 0;
  371.     macbin = 0;
  372.     flatten = 0;
  373.     numfiles = 0;
  374.     depth = 0;
  375.  
  376.     while ((c = getopt(argc, argv, "dflmqruvx")) != EOF)
  377.     switch (c) {
  378.       case 'r':
  379.         mode = RSRC;
  380.         break;
  381.       case 'd':
  382.         mode = DATA;
  383.         break;
  384.       case 'u':
  385.         mode = TEXT;
  386.         break;
  387.       case 'l':
  388.         listonly++;
  389.         break;
  390.       case 'q':
  391.         query++;
  392.         break;
  393.       case 'v':
  394.         verbose++;
  395.         break;
  396.       case 'x':
  397.         mode = DUMP;
  398.         break;
  399.       case 'm':
  400.         macbin = 1;
  401.         break;
  402.       case 'f':
  403.         flatten = 1;
  404.         break;
  405.       case '?':
  406.         errflg++;
  407.         break;
  408.     }
  409.     if (errflg) {
  410.     usage();
  411.     exit(1);
  412.     }
  413.  
  414.     if (optind == argc) {
  415.     usage();
  416.     exit(1);
  417.     }
  418.     else {
  419.     if ((infp = fopen(argv[optind], "r")) == NULL) {
  420.         fprintf(stderr,"Can't open input file \"%s\"\n",argv[optind]);
  421.         exit(1);
  422.     }
  423.     }
  424.  
  425.     if (macbin) {
  426.     if (fseek(infp, MACBINHDRSIZE, 0) == -1) {
  427.         fprintf(stderr, "Can't skip over MacBinary header\n");
  428.         exit(1);
  429.     }
  430.     }
  431.  
  432.     if (readsithdr(&sithdr) == 0) {
  433.     fprintf(stderr, "Can't read file header\n");
  434.     exit(1);
  435.     }
  436.     /* 
  437.     printf("numfiles=%d, arclength=%ld\n", sithdr.numFiles, sithdr.arcLength);
  438.     */
  439.     
  440.     status = extract("", 0);
  441.     exit((status < 0) ? 1 : 0);
  442. }
  443.  
  444. usage()
  445. {
  446.     fprintf(stderr, "Usage: unsit [-rdulvqmf] filename\n");
  447. }
  448.  
  449. /*
  450.   extract(parent, skip) - Extract all files from the current folder.
  451.   char *parent;           name of parent folder
  452.   int  skip;              1 to skip all files and folders in this one
  453.                           0 to extract them
  454.  
  455.   returns 1 if came an endFolder record
  456.           0 if EOF
  457.      -1 if error (bad fileHdr, bad file, etc.)
  458. */
  459.  
  460. extract(parent, skip)
  461. char *parent;
  462. int skip;
  463. {
  464.     struct fileHdr filehdr;
  465.     struct stat sbuf;
  466.     int status, rstat, sstat, skipit;
  467.     char name[256];
  468.  
  469.     while (1) {
  470.     rstat = readfilehdr(&filehdr, skip);
  471.     if (rstat == H_ERROR || rstat == H_EOF) {
  472.         status = rstat;
  473.         break;
  474.     }
  475.     /*
  476.     printf("compr=%d, compd=%d, rsrclen=%ld, datalen=%ld, rsrccrc=%d, datacrc=%d\n",
  477.            filehdr.compRMethod, filehdr.compDMethod,
  478.            filehdr.compRLength, filehdr.compDLength,
  479.            filehdr.rsrcCRC, filehdr.dataCRC);
  480.     */
  481.  
  482.     skipit = (rstat == H_SKIP) ? 1 : 0;
  483.  
  484.     if (filehdr.compRMethod == endFolder && 
  485.         filehdr.compDMethod == endFolder) {
  486.         status = 1;        /* finished with this folder */
  487.         break;
  488.     }
  489.     else if (filehdr.compRMethod == startFolder && 
  490.          filehdr.compDMethod == startFolder) {
  491.         if (!listonly && rstat == H_WRITE && !flatten) {
  492.         sstat = stat(uname, &sbuf);
  493.         if (sstat == -1) {    /* directory doesn't exist */
  494.             if (mkdir(uname, 0777) == -1) {
  495.             fprintf(stderr,
  496.                 "Can't create subdirectory %s\n", uname);
  497.             return(-1);
  498.             }
  499.         }
  500.         else {        /* something exists with this name */
  501.             if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
  502.             fprintf(stderr, "Directory name %s already in use\n",
  503.                 uname);
  504.             return(-1);
  505.             }
  506.         }
  507.         if (chdir(uname) == -1) {
  508.             fprintf(stderr, "Can't chdir to %s\n", uname);
  509.             return(-1);
  510.         }
  511.         sprintf(name,"%s:%s", parent, uname);
  512.         }
  513.         depth++;
  514.         status = extract(name, skipit);
  515.         depth--;
  516.         if (status != 1)
  517.         break;        /* problem with folder */
  518.         if (depth == 0)    /* count how many top-level files done */
  519.         numfiles++;
  520.         if (!flatten)
  521.         chdir("..");
  522.     }
  523.     else {
  524.         if ((status = extractfile(&filehdr, skipit)) != 1)
  525.         break;
  526.         if (depth == 0)    /* count how many top-level files done */
  527.         numfiles++;
  528.     }
  529.     if (numfiles == sithdr.numFiles)
  530.         break;
  531.     }
  532.     return(status);
  533. }
  534.  
  535. extractfile(fh, skip)
  536. struct fileHdr *fh;
  537. int skip;
  538. {
  539.     unsigned short crc;
  540.     FILE *fp;
  541.  
  542.     f_data[0] = f_rsrc[0] = f_info[0] = '\0'; /* assume no output files */
  543.     /* figure out what file names to use and what to do */
  544.     if (!listonly && !skip) {
  545.     switch (mode) {
  546.       case FULL:        /* do both rsrc and data forks */
  547.         sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
  548.         sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
  549.         sprintf(f_info, "%.*s.info", I_NAMELEN - 6, uname);
  550.         break;
  551.       case RSRC:        /* rsrc fork only */
  552.         sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
  553.         break;
  554.       case DATA:        /* data fork only */
  555.       case TEXT:
  556.         sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
  557.         break;
  558.       case DUMP:        /* for debugging, dump data as is */
  559.         sprintf(f_data, "%.*s.ddump", I_NAMELEN - 7, uname);
  560.         sprintf(f_rsrc, "%.*s.rdump", I_NAMELEN - 7, uname);
  561.         fh->compRMethod = fh->compDMethod = noComp;
  562.         break;
  563.     }
  564.     }
  565.  
  566.     if (f_info[0] != '\0' && check_access(f_info) != -1) {
  567.     fp = fopen(f_info, "w");
  568.     if (fp == NULL) {
  569.         perror(f_info);
  570.         exit(1);
  571.     }
  572.     fwrite(info, 1, INFOBYTES, fp);
  573.     fclose(fp);
  574.     }
  575.  
  576.     if (f_rsrc[0] != '\0') {
  577.     txtmode = 0;
  578.     crc = write_file(f_rsrc, fh->compRLength,
  579.              fh->rsrcLength, fh->compRMethod);
  580.     if (chkcrc && fh->rsrcCRC != crc) {
  581.         fprintf(stderr,
  582.             "CRC error on resource fork: need 0x%04x, got 0x%04x\n",
  583.             fh->rsrcCRC, crc);
  584.         return(-1);
  585.     }
  586.     }
  587.     else {
  588.     fseek(infp, (long) fh->compRLength, 1);
  589.     }
  590.     if (f_data[0] != '\0') {
  591.     txtmode = (mode == TEXT);
  592.     crc = write_file(f_data, fh->compDLength,
  593.              fh->dataLength, fh->compDMethod);
  594.     if (chkcrc && fh->dataCRC != crc) {
  595.         fprintf(stderr,
  596.             "CRC error on data fork: need 0x%04x, got 0x%04x\n",
  597.             fh->dataCRC, crc);
  598.         return(-1);
  599.     }
  600.     }
  601.     else {
  602.     fseek(infp, (long) fh->compDLength, 1);
  603.     }
  604.     return(1);
  605. }
  606.  
  607. readsithdr(s)
  608. struct sitHdr *s;
  609. {
  610.     char temp[FILEHDRSIZE];
  611.     int count = 0;
  612.  
  613.     for (;;) {
  614.     if (fread(temp, 1, SITHDRSIZE, infp) != SITHDRSIZE) {
  615.         fprintf(stderr, "Can't read file header\n");
  616.         return(0);
  617.     }
  618.         
  619.     if (strncmp(temp + S_SIGNATURE,  "SIT!", 4) == 0 &&
  620.         strncmp(temp + S_SIGNATURE2, "rLau", 4) == 0) {
  621.         s->numFiles = get2(temp + S_NUMFILES);
  622.         s->arcLength = get4(temp + S_ARCLENGTH);
  623.         return(1);
  624.     }
  625.     
  626.     if (++count == 2) {
  627.         fprintf(stderr, "Not a StuffIt file\n");
  628.         return(0);
  629.     }
  630.     
  631.     if (fread(&temp[SITHDRSIZE], 1, FILEHDRSIZE - SITHDRSIZE, infp) !=
  632.         FILEHDRSIZE - SITHDRSIZE) {
  633.         fprintf(stderr, "Can't read file header\n");
  634.         return(0);
  635.     }
  636.     
  637.     if (strncmp(temp + I_TYPEOFF, "SIT!", 4) == 0 &&
  638.         strncmp(temp + I_AUTHOFF, "SIT!", 4) == 0) {    /* MacBinary format */
  639.         fseek(infp, (long)(INFOBYTES-FILEHDRSIZE), 1);    /* Skip over header */
  640.     }
  641.     }
  642. }
  643.  
  644. /*
  645.   readfilehdr - reads the file header for each file and the folder start
  646.   and end records.
  647.  
  648.   returns: H_ERROR = error
  649.        H_EOF   = EOF
  650.        H_WRITE = write file/folder
  651.        H_SKIP  = skip file/folder
  652. */
  653.  
  654. readfilehdr(f, skip)
  655. struct fileHdr *f;
  656. int skip;
  657. {
  658.     unsigned short crc;
  659.     int i, n, write_it, isfolder;
  660.     char hdr[FILEHDRSIZE];
  661.     char ch, *mp, *up;
  662.     char *tp, temp[10];
  663.  
  664.     for (i = 0; i < INFOBYTES; i++)
  665.     info[i] = '\0';
  666.  
  667.     /* read in the next file header, which could be folder start/end record */
  668.     n = fread(hdr, 1, FILEHDRSIZE, infp);
  669.     if (n == 0)            /* return 0 on EOF */
  670.     return(H_EOF);
  671.     else if (n != FILEHDRSIZE) {
  672.     fprintf(stderr, "Can't read file header\n");
  673.     return(H_ERROR);
  674.     }
  675.  
  676.     /* check the CRC for the file header */
  677.     crc = INIT_CRC;
  678.     crc = updcrc(crc, hdr, FILEHDRSIZE - 2);
  679.     f->hdrCRC = get2(hdr + F_HDRCRC);
  680.     if (f->hdrCRC != crc) {
  681.     fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
  682.         f->hdrCRC, crc);
  683.     return(H_ERROR);
  684.     }
  685.  
  686.     /* grab the name of the file or folder */
  687.     n = hdr[F_FNAME] & BYTEMASK;
  688.     if (n > F_NAMELEN)
  689.     n = F_NAMELEN;
  690.     info[I_NAMEOFF] = n;
  691.     copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n);
  692.     strncpy(mname, hdr + F_FNAME + 1, n);
  693.     mname[n] = '\0';
  694.     /* copy to a string with no illegal Unix characters in the file name */
  695.     mp = mname;
  696.     up = uname;
  697.     while ((ch = *mp++) != '\0') {
  698.     if (ch <= ' ' || ch > '~' || index("/!()[]*<>?\\\"$\';&`", ch) != NULL)
  699.         ch = '_';
  700.     *up++ = ch;
  701.     }
  702.     *up = '\0';
  703.  
  704.     /* get lots of other stuff from the header */
  705.     f->compRMethod = hdr[F_COMPRMETHOD];
  706.     f->compDMethod = hdr[F_COMPDMETHOD];
  707.     f->rsrcLength = get4(hdr + F_RSRCLENGTH);
  708.     f->dataLength = get4(hdr + F_DATALENGTH);
  709.     f->compRLength = get4(hdr + F_COMPRLENGTH);
  710.     f->compDLength = get4(hdr + F_COMPDLENGTH);
  711.     f->rsrcCRC = get2(hdr + F_RSRCCRC);
  712.     f->dataCRC = get2(hdr + F_DATACRC);
  713.  
  714.     /* if it's an end folder record, don't need to do any more */
  715.     if (f->compRMethod == endFolder && f->compDMethod == endFolder)
  716.     return(H_WRITE);
  717.  
  718.     /* prepare an info file in case its needed */
  719.  
  720.     copy(info + I_TYPEOFF, hdr + F_FTYPE, 4);
  721.     copy(info + I_AUTHOFF, hdr + F_CREATOR, 4);
  722.     copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2);
  723. #ifdef INITED_BUG
  724.     info[INITED_OFF] &= INITED_MASK; /* reset init bit */
  725. #endif
  726.     copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4);
  727.     copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4);
  728.     copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4);
  729.     copy(info + I_MTIMOFF, hdr + F_MODDATE, 4);
  730.  
  731.     isfolder = f->compRMethod == startFolder && f->compDMethod == startFolder;
  732.     
  733.     /* list the file name if verbose or listonly mode, also if query mode */
  734.     if (skip)            /* skip = 1 if skipping all in this folder */
  735.     write_it = 0;
  736.     else {
  737.     write_it = 1;
  738.     if (listonly || verbose || query) {
  739.         for (i = 0; i < depth; i++)
  740.         putchar(' ');
  741.         if (isfolder)
  742.         printf("Folder: \"%s\"", uname);
  743.         else
  744.         printf("name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  745.                uname, hdr + F_FTYPE, hdr + F_CREATOR,
  746.                f->dataLength, f->rsrcLength);
  747.         if (query) {    /* if querying, check with the boss */
  748.         printf(" ? ");
  749.         fgets(temp, sizeof(temp) - 1, stdin);
  750.         tp = temp;
  751.         write_it = 0;
  752.         while (*tp != '\0') {
  753.             if (*tp == 'y' || *tp == 'Y') {
  754.             write_it = 1;
  755.             break;
  756.             }
  757.             else
  758.             tp++;
  759.         }
  760.         }
  761.         else        /* otherwise, terminate the line */
  762.         putchar('\n');
  763.     }
  764.     }
  765.     return(write_it ? H_WRITE : H_SKIP);
  766. }
  767.  
  768. check_access(fname)    /* return 0 if OK to write on file fname, -1 otherwise */
  769. char *fname;
  770. {
  771.     char temp[10], *tp;
  772.  
  773.     if (access(fname, 0) == -1) {
  774.     return(0);
  775.     }
  776.     else {
  777.     printf("%s exists.  Overwrite? ", fname);
  778.     fgets(temp, sizeof(temp) - 1, stdin);
  779.     tp = temp;
  780.     while (*tp != '\0') {
  781.         if (*tp == 'y' || *tp == 'Y') {
  782.         return(0);
  783.         }
  784.         else
  785.         tp++;
  786.     }
  787.     }
  788.     return(-1);
  789. }
  790.  
  791. unsigned short write_file(fname, ibytes, obytes, type)
  792. char *fname;
  793. unsigned long ibytes, obytes;
  794. unsigned char type;
  795. {
  796.     unsigned short crc;
  797.     int i, n, ch, lastch;
  798.     FILE *outf;
  799.     char temp[256];
  800.  
  801.     crc = INIT_CRC;
  802.     chkcrc = 1;            /* usually can check the CRC */
  803.  
  804.     if (check_access(fname) == -1) {
  805.     fseek(infp, ibytes, 1);
  806.     chkcrc = 0;        /* inhibit crc check if file not written */
  807.         return(-1);
  808.     }
  809.     
  810.     switch (type) {
  811.       case noComp:        /* no compression */
  812.     outf = fopen(fname, "w");
  813.     if (outf == NULL) {
  814.         perror(fname);
  815.         exit(1);
  816.     }
  817.     while (ibytes > 0) {
  818.         n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
  819.         n = fread(iobuf, 1, n, infp);
  820.         if (n == 0)
  821.         break;
  822.         crc = updcrc(crc, iobuf, n);
  823.         outc(iobuf, n, outf);
  824.         ibytes -= n;
  825.     }
  826.     fclose(outf);
  827.     break;
  828.       case rleComp:        /* run length encoding */
  829.     outf = fopen(fname, "w");
  830.     if (outf == NULL) {
  831.         perror(fname);
  832.         exit(1);
  833.     }
  834.     while (ibytes > 0) {
  835.         ch = getc(infp) & 0xff;
  836.         ibytes--;
  837.         if (ch == 0x90) {    /* see if its the repeat marker */
  838.         n = getc(infp) & 0xff; /* get the repeat count */
  839.         ibytes--;
  840.         if (n == 0) { /* 0x90 was really an 0x90 */
  841.             iobuf[0] = 0x90;
  842.             crc = updcrc(crc, iobuf, 1);
  843.             outc(iobuf, 1, outf);
  844.         }
  845.         else {
  846.             n--;
  847.             for (i = 0; i < n; i++)
  848.             iobuf[i] = lastch;
  849.             crc = updcrc(crc, iobuf, n);
  850.             outc(iobuf, n, outf);
  851.         }
  852.         }
  853.         else {
  854.         iobuf[0] = ch;
  855.         crc = updcrc(crc, iobuf, 1);
  856.         lastch = ch;
  857.         outc(iobuf, 1, outf);
  858.         }
  859.     }
  860.     fclose(outf);
  861.     break;
  862.       case lzwComp:        /* LZW compression */
  863.     sprintf(temp, "%s%s", COMPRESS, " -d -c -n -b 14 ");
  864.     if (txtmode) {
  865.         strcat(temp, "| tr \'\\015\' \'\\012\' ");
  866.         chkcrc = 0;        /* can't check CRC in this case */
  867.     }
  868.     strcat(temp, "> '");
  869.     strcat(temp, fname);
  870.     strcat(temp, "'");
  871.     outf = popen(temp, "w");
  872.     if (outf == NULL) {
  873.         perror(fname);
  874.         exit(1);
  875.     }
  876.     while (ibytes > 0) {
  877.         n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
  878.         n = fread(iobuf, 1, n, infp);
  879.         if (n == 0)
  880.         break;
  881.         fwrite(iobuf, 1, n, outf);
  882.         ibytes -= n;
  883.     }
  884.     pclose(outf);
  885.     if (chkcrc) {
  886.         outf = fopen(fname, "r"); /* read the file to get CRC value */
  887.         if (outf == NULL) {
  888.         perror(fname);
  889.         exit(1);
  890.         }
  891.         while (1) {
  892.         n = fread(iobuf, 1, IOBUFSIZ, outf);
  893.         if (n == 0)
  894.             break;
  895.         crc = updcrc(crc, iobuf, n);
  896.         }
  897.         fclose(outf);
  898.     }
  899.     break;
  900.       case hufComp:        /* Huffman compression */
  901.     outf = fopen(fname, "w");
  902.     if (outf == NULL) {
  903.         perror(fname);
  904.         exit(1);
  905.     }
  906.     nodeptr = nodelist;
  907.     bit = 0;        /* put us on a byte boundary */
  908.     read_tree();
  909.     while (obytes > 0) {
  910.         n = (obytes > IOBUFSIZ) ? IOBUFSIZ : obytes;
  911.         for (i = 0; i < n; i++)
  912.         iobuf[i] = gethuffbyte(DECODE);
  913.         crc = updcrc(crc, iobuf, n);
  914.         outc(iobuf, n, outf);
  915.         obytes -= n;
  916.     }
  917.     fclose(outf);
  918.     break;
  919.       default:
  920.     fprintf(stderr, "Unknown compression method\n");
  921.     chkcrc = 0;        /* inhibit crc check if file not written */
  922.     return(-1);
  923.     }
  924.  
  925.     return(crc & 0xffff);
  926. }
  927.  
  928. outc(p, n, fp)
  929. char *p;
  930. int n;
  931. FILE *fp;
  932. {
  933.     register char *p1;
  934.     register int i;
  935.     if (txtmode) {
  936.     for (i = 0, p1 = p; i < n; i++, p1++)
  937.         if ((*p1 & BYTEMASK) == '\r')
  938.         *p1 = '\n';
  939.     }
  940.     fwrite(p, 1, n, fp);
  941. }
  942.  
  943. long get4(bp)
  944. char *bp;
  945. {
  946.     register int i;
  947.     long value = 0;
  948.  
  949.     for (i = 0; i < 4; i++) {
  950.     value <<= 8;
  951.     value |= (*bp & BYTEMASK);
  952.     bp++;
  953.     }
  954.     return(value);
  955. }
  956.  
  957. short get2(bp)
  958. char *bp;
  959. {
  960.     register int i;
  961.     int value = 0;
  962.  
  963.     for (i = 0; i < 2; i++) {
  964.     value <<= 8;
  965.     value |= (*bp & BYTEMASK);
  966.     bp++;
  967.     }
  968.     return(value);
  969. }
  970.  
  971. copy(p1, p2, n)
  972. char *p1, *p2;
  973. int n;
  974. {
  975.     while (n-- > 0)
  976.         *p1++ = *p2++;
  977. }
  978.  
  979. /* This routine recursively reads the Huffman encoding table and builds
  980.    and decoding tree. */
  981.  
  982. struct node *read_tree()
  983. {
  984.     struct node *np;
  985.     np = nodeptr++;
  986.     if (getbit() == 1) {
  987.         np->flag = 1;
  988.         np->byte = gethuffbyte(NODECODE);
  989.     }
  990.     else {
  991.         np->flag = 0;
  992.         np->zero = read_tree();
  993.         np->one  = read_tree();
  994.     }
  995.     return(np);
  996. }
  997.  
  998. /* This routine returns the next bit in the input stream (MSB first) */
  999.  
  1000. getbit()
  1001. {
  1002.     static char b;
  1003.     if (bit == 0) {
  1004.         b = getc(infp) & 0xff;
  1005.         bit = 8;
  1006.     }
  1007.     bit--;
  1008.     return((b >> bit) & 1);
  1009. }
  1010.  
  1011. /* This routine returns the next 8 bits.  If decoding is on, it finds the
  1012. byte in the decoding tree based on the bits from the input stream.  If
  1013. decoding is not on, it either gets it directly from the input stream or
  1014. puts it together from 8 calls to getbit(), depending on whether or not we
  1015. are currently on a byte boundary
  1016. */
  1017. gethuffbyte(decode)
  1018. int decode;
  1019. {
  1020.     register struct node *np;
  1021.     register int i, b;
  1022.     if (decode == DECODE) {
  1023.         np = nodelist;
  1024.         while (np->flag == 0)
  1025.             np = (getbit()) ? np->one : np->zero;
  1026.         b = np->byte;
  1027.     }
  1028.     else {
  1029.         if (bit == 0)    /* on byte boundary? */
  1030.             b = getc(infp) & 0xff;
  1031.         else {        /* no, put a byte together */
  1032.             b = 0;
  1033.             for (i = 8; i > 0; i--) {
  1034.                 b = (b << 1) + getbit();
  1035.             }
  1036.         }
  1037.     }
  1038.     return(b);
  1039. }
  1040. SHAR_EOF
  1041. fi # end of overwriting check
  1042. if test -f 'stuffit.h'
  1043. then
  1044.     echo shar: will not over-write existing file "'stuffit.h'"
  1045. else
  1046. cat << \SHAR_EOF > 'stuffit.h'
  1047. /* StuffIt.h: contains declarations for SIT headers */
  1048.  
  1049. typedef struct sitHdr {            /* 22 bytes */
  1050.     OSType    signature;         /* = 'SIT!' -- for verification */
  1051.     unsigned short    numFiles;    /* number of files in archive */
  1052.     unsigned long    arcLength;    /* length of entire archive incl.
  1053.                         hdr. -- for verification */
  1054.     OSType    signature2;        /* = 'rLau' -- for verification */
  1055.     unsigned char    version;    /* version number */
  1056.     char reserved[7];
  1057. };
  1058.  
  1059. typedef struct fileHdr {        /* 112 bytes */
  1060.     unsigned char    compRMethod;    /* rsrc fork compression method */
  1061.     unsigned char    compDMethod;    /* data fork compression method */
  1062.     unsigned char    fName[64];    /* a STR63 */
  1063.     OSType    fType;            /* file type */
  1064.     OSType    fCreator;        /* er... */
  1065.     short FndrFlags;        /* copy of Finder flags.  For our
  1066.                         purposes, we can clear:
  1067.                         busy,onDesk */
  1068.     unsigned long    creationDate;
  1069.     unsigned long    modDate;    /* !restored-compat w/backup prgms */
  1070.     unsigned long    rsrcLength;    /* decompressed lengths */
  1071.     unsigned long    dataLength;
  1072.     unsigned long    compRLength;    /* compressed lengths */
  1073.     unsigned long    compDLength;
  1074.     unsigned short rsrcCRC;        /* crc of rsrc fork */
  1075.     unsigned short dataCRC;        /* crc of data fork */
  1076.     char reserved[6];
  1077.     unsigned short hdrCRC;        /* crc of file header */
  1078. };
  1079.  
  1080.  
  1081. /* file format is:
  1082.     sitArchiveHdr
  1083.         file1Hdr
  1084.             file1RsrcFork
  1085.             file1DataFork
  1086.         file2Hdr
  1087.             file2RsrcFork
  1088.             file2DataFork
  1089.         .
  1090.         .
  1091.         .
  1092.         fileNHdr
  1093.             fileNRsrcFork
  1094.             fileNDataFork
  1095. */
  1096.  
  1097.  
  1098.  
  1099. /* compression methods */
  1100. #define noComp     0    /* just read each byte and write it to archive */
  1101. #define rleComp 1    /* RLE compression */
  1102. #define lzwComp 2    /* LZW compression */
  1103. #define hufComp 3    /* Huffman compression */
  1104.  
  1105. #define encrypted 16    /* bit set if encrypted.  ex: encrypted+lpzComp */
  1106.  
  1107. #define startFolder 32    /* marks start of a new folder */
  1108. #define endFolder 33    /* marks end of the last folder "started" */
  1109.  
  1110. /* all other numbers are reserved */
  1111. SHAR_EOF
  1112. fi # end of overwriting check
  1113. if test -f 'updcrc.c'
  1114. then
  1115.     echo shar: will not over-write existing file "'updcrc.c'"
  1116. else
  1117. cat << \SHAR_EOF > 'updcrc.c'
  1118. /* updcrc(3), crc(1) - calculate crc polynomials
  1119.  *
  1120.  * Calculate, intelligently, the CRC of a dataset incrementally given a 
  1121.  * buffer full at a time.
  1122.  * 
  1123.  * Usage:
  1124.  *     newcrc = updcrc( oldcrc, bufadr, buflen )
  1125.  *         unsigned int oldcrc, buflen;
  1126.  *         char *bufadr;
  1127.  *
  1128.  * Compiling with -DTEST creates a program to print the CRC of stdin to stdout.
  1129.  * Compile with -DMAKETAB to print values for crctab to stdout.  If you change
  1130.  *    the CRC polynomial parameters, be sure to do this and change
  1131.  *    crctab's initial value.
  1132.  *
  1133.  * Notes:
  1134.  *  Regards the data stream as an integer whose MSB is the MSB of the first
  1135.  *  byte recieved.  This number is 'divided' (using xor instead of subtraction)
  1136.  *  by the crc-polynomial P.
  1137.  *  XMODEM does things a little differently, essentially treating the LSB of
  1138.  * the first data byte as the MSB of the integer. Define SWAPPED to make
  1139.  * things behave in this manner.
  1140.  *
  1141.  * Author:    Mark G. Mendel, 7/86
  1142.  *        UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm
  1143.  */
  1144.  
  1145. /* The CRC polynomial.
  1146.  * These 4 values define the crc-polynomial.
  1147.  * If you change them, you must change crctab[]'s initial value to what is
  1148.  * printed by initcrctab() [see 'compile with -DMAKETAB' above].
  1149.  */
  1150.     /* Value used by:                CITT    XMODEM    ARC      */
  1151. #define    P     0xA001     /* the poly:    0x1021    0x1021    A001    */
  1152. #define INIT_CRC 0L     /* init value:    -1    0    0    */
  1153. #define SWAPPED         /* bit order:    undef    defined    defined */
  1154. #define W    16     /* bits in CRC:16    16    16    */
  1155.  
  1156.     /* data type that holds a W-bit unsigned integer */
  1157. #if W <= 16
  1158. #  define WTYPE    unsigned short
  1159. #else
  1160. #  define WTYPE   unsigned long
  1161. #endif
  1162.  
  1163.     /* the number of bits per char: don't change it. */
  1164. #define B    8
  1165.  
  1166. static WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ {
  1167. 0x0,  0xc0c1,  0xc181,  0x140,  0xc301,  0x3c0,  0x280,  0xc241,
  1168. 0xc601,  0x6c0,  0x780,  0xc741,  0x500,  0xc5c1,  0xc481,  0x440,
  1169. 0xcc01,  0xcc0,  0xd80,  0xcd41,  0xf00,  0xcfc1,  0xce81,  0xe40,
  1170. 0xa00,  0xcac1,  0xcb81,  0xb40,  0xc901,  0x9c0,  0x880,  0xc841,
  1171. 0xd801,  0x18c0,  0x1980,  0xd941,  0x1b00,  0xdbc1,  0xda81,  0x1a40,
  1172. 0x1e00,  0xdec1,  0xdf81,  0x1f40,  0xdd01,  0x1dc0,  0x1c80,  0xdc41,
  1173. 0x1400,  0xd4c1,  0xd581,  0x1540,  0xd701,  0x17c0,  0x1680,  0xd641,
  1174. 0xd201,  0x12c0,  0x1380,  0xd341,  0x1100,  0xd1c1,  0xd081,  0x1040,
  1175. 0xf001,  0x30c0,  0x3180,  0xf141,  0x3300,  0xf3c1,  0xf281,  0x3240,
  1176. 0x3600,  0xf6c1,  0xf781,  0x3740,  0xf501,  0x35c0,  0x3480,  0xf441,
  1177. 0x3c00,  0xfcc1,  0xfd81,  0x3d40,  0xff01,  0x3fc0,  0x3e80,  0xfe41,
  1178. 0xfa01,  0x3ac0,  0x3b80,  0xfb41,  0x3900,  0xf9c1,  0xf881,  0x3840,
  1179. 0x2800,  0xe8c1,  0xe981,  0x2940,  0xeb01,  0x2bc0,  0x2a80,  0xea41,
  1180. 0xee01,  0x2ec0,  0x2f80,  0xef41,  0x2d00,  0xedc1,  0xec81,  0x2c40,
  1181. 0xe401,  0x24c0,  0x2580,  0xe541,  0x2700,  0xe7c1,  0xe681,  0x2640,
  1182. 0x2200,  0xe2c1,  0xe381,  0x2340,  0xe101,  0x21c0,  0x2080,  0xe041,
  1183. 0xa001,  0x60c0,  0x6180,  0xa141,  0x6300,  0xa3c1,  0xa281,  0x6240,
  1184. 0x6600,  0xa6c1,  0xa781,  0x6740,  0xa501,  0x65c0,  0x6480,  0xa441,
  1185. 0x6c00,  0xacc1,  0xad81,  0x6d40,  0xaf01,  0x6fc0,  0x6e80,  0xae41,
  1186. 0xaa01,  0x6ac0,  0x6b80,  0xab41,  0x6900,  0xa9c1,  0xa881,  0x6840,
  1187. 0x7800,  0xb8c1,  0xb981,  0x7940,  0xbb01,  0x7bc0,  0x7a80,  0xba41,
  1188. 0xbe01,  0x7ec0,  0x7f80,  0xbf41,  0x7d00,  0xbdc1,  0xbc81,  0x7c40,
  1189. 0xb401,  0x74c0,  0x7580,  0xb541,  0x7700,  0xb7c1,  0xb681,  0x7640,
  1190. 0x7200,  0xb2c1,  0xb381,  0x7340,  0xb101,  0x71c0,  0x7080,  0xb041,
  1191. 0x5000,  0x90c1,  0x9181,  0x5140,  0x9301,  0x53c0,  0x5280,  0x9241,
  1192. 0x9601,  0x56c0,  0x5780,  0x9741,  0x5500,  0x95c1,  0x9481,  0x5440,
  1193. 0x9c01,  0x5cc0,  0x5d80,  0x9d41,  0x5f00,  0x9fc1,  0x9e81,  0x5e40,
  1194. 0x5a00,  0x9ac1,  0x9b81,  0x5b40,  0x9901,  0x59c0,  0x5880,  0x9841,
  1195. 0x8801,  0x48c0,  0x4980,  0x8941,  0x4b00,  0x8bc1,  0x8a81,  0x4a40,
  1196. 0x4e00,  0x8ec1,  0x8f81,  0x4f40,  0x8d01,  0x4dc0,  0x4c80,  0x8c41,
  1197. 0x4400,  0x84c1,  0x8581,  0x4540,  0x8701,  0x47c0,  0x4680,  0x8641,
  1198. 0x8201,  0x42c0,  0x4380,  0x8341,  0x4100,  0x81c1,  0x8081,  0x4040,
  1199. } ;
  1200.  
  1201. WTYPE
  1202. updcrc( icrc, icp, icnt )
  1203.     WTYPE icrc;
  1204.     unsigned char *icp;
  1205.     int icnt;
  1206. {
  1207.     register WTYPE crc = icrc;
  1208.     register unsigned char *cp = icp;
  1209.     register int cnt = icnt;
  1210.  
  1211.     while( cnt-- ) {
  1212. #ifndef SWAPPED
  1213.     crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
  1214. #else
  1215.     crc = (crc>>B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++]; 
  1216. #endif SWAPPED
  1217.     }
  1218.  
  1219.     return( crc );
  1220. }
  1221.  
  1222. #ifdef MAKETAB
  1223.  
  1224. #include <stdio.h>
  1225. main()
  1226. {
  1227.     initcrctab();
  1228. }
  1229.  
  1230. initcrctab()
  1231. {
  1232.     register  int b, i;
  1233.     WTYPE v;
  1234.  
  1235.     
  1236.     for( b = 0; b <= (1<<B)-1; ++b ) {
  1237. #ifndef SWAPPED
  1238.     for( v = b<<(W-B), i = B; --i >= 0; )
  1239.         v = v & ((WTYPE)1<<(W-1)) ? (v<<1)^P : v<<1;
  1240. #else
  1241.     for( v = b, i = B; --i >= 0; )
  1242.         v = v & 1 ? (v>>1)^P : v>>1;
  1243. #endif        
  1244.     crctab[b] = v;
  1245.  
  1246.     printf( "0x%lx,", v & ((1L<<W)-1L));
  1247.     if( (b&7) == 7 )
  1248.         printf("\n" );
  1249.     else
  1250.         printf("  ");
  1251.     }
  1252. }
  1253. #endif
  1254.  
  1255. #ifdef TEST
  1256.  
  1257. #include <stdio.h>
  1258. #include <fcntl.h>
  1259.  
  1260. #define MAXBUF    4096
  1261.  
  1262.  
  1263.  
  1264. main( ac, av )
  1265.     int ac; char **av;
  1266. {
  1267.     int fd;
  1268.     int nr;
  1269.     int i;
  1270.     char buf[MAXBUF];
  1271.     WTYPE crc, crc2;
  1272.  
  1273.     fd = 0;
  1274.     if( ac > 1 )
  1275.     if( (fd = open( av[1], O_RDONLY )) < 0 ) {
  1276.         perror( av[1] );
  1277.         exit( -1 );
  1278.     }
  1279.     crc = crc2 = INIT_CRC;
  1280.  
  1281.     while( (nr = read( fd, buf, MAXBUF )) > 0 ) {
  1282.     crc = updcrc( crc, buf, nr );
  1283.     }
  1284.  
  1285.     if( nr != 0 )
  1286.     perror( "reading" );
  1287.     else {
  1288.     printf( "%lx\n", crc );
  1289.     }
  1290.  
  1291. #ifdef MAGICCHECK
  1292.     /* tack one's complement of crc onto data stream, and
  1293.        continue crc calculation.  Should get a constant (magic number)
  1294.        dependent only on P, not the data.
  1295.      */
  1296.     crc2 = crc ^ -1L;
  1297.     for( nr = W-B; nr >= 0; nr -= B ) {
  1298.     buf[0] = (crc2 >> nr);
  1299.     crc = updcrc(crc, buf, 1);
  1300.     }
  1301.  
  1302.     /* crc should now equal magic */
  1303.     buf[0] = buf[1] = buf[2] = buf[3] = 0;
  1304.     printf( "magic test: %lx =?= %lx\n", crc, updcrc(-1, buf, W/B));
  1305. #endif MAGICCHECK
  1306. }
  1307.  
  1308. #endif
  1309. SHAR_EOF
  1310. fi # end of overwriting check
  1311. if test -f 'getopt.c'
  1312. then
  1313.     echo shar: will not over-write existing file "'getopt.c'"
  1314. else
  1315. cat << \SHAR_EOF > 'getopt.c'
  1316. /*
  1317.  * getopt - get option letter from argv
  1318.  */
  1319.  
  1320. #include <stdio.h>
  1321.  
  1322. char    *optarg;    /* Global argument pointer. */
  1323. int    optind = 0;    /* Global argv index. */
  1324.  
  1325. static char    *scan = NULL;    /* Private scan pointer. */
  1326.  
  1327. extern char    *index();
  1328.  
  1329. int
  1330. getopt(argc, argv, optstring)
  1331. int argc;
  1332. char *argv[];
  1333. char *optstring;
  1334. {
  1335.     register char c;
  1336.     register char *place;
  1337.  
  1338.     optarg = NULL;
  1339.  
  1340.     if (scan == NULL || *scan == '\0') {
  1341.         if (optind == 0)
  1342.             optind++;
  1343.     
  1344.         if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  1345.             return(EOF);
  1346.         if (strcmp(argv[optind], "--")==0) {
  1347.             optind++;
  1348.             return(EOF);
  1349.         }
  1350.     
  1351.         scan = argv[optind]+1;
  1352.         optind++;
  1353.     }
  1354.  
  1355.     c = *scan++;
  1356.     place = index(optstring, c);
  1357.  
  1358.     if (place == NULL || c == ':') {
  1359.         fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
  1360.         return('?');
  1361.     }
  1362.  
  1363.     place++;
  1364.     if (*place == ':') {
  1365.         if (*scan != '\0') {
  1366.             optarg = scan;
  1367.             scan = NULL;
  1368.         } else if (optind < argc) {
  1369.             optarg = argv[optind];
  1370.             optind++;
  1371.         } else {
  1372.             fprintf(stderr, "%s: -%c argument missing\n", argv[0], c);
  1373.             return('?');
  1374.         }
  1375.     }
  1376.  
  1377.     return(c);
  1378. }
  1379.  
  1380. SHAR_EOF
  1381. fi # end of overwriting check
  1382. if test -f 'unsit.1'
  1383. then
  1384.     echo shar: will not over-write existing file "'unsit.1'"
  1385. else
  1386. cat << \SHAR_EOF > 'unsit.1'
  1387. .TH UNSIT L "Septermber 28, 1988"
  1388. .UC
  1389. .SH NAME
  1390. unsit \- extract/list files in a Macintosh Stuffit archive file
  1391. .SH SYNOPSIS
  1392. .B unsit
  1393. [
  1394. .B \-dflmqruv
  1395. ] file
  1396. .br
  1397. .SH DESCRIPTION
  1398. For the Stuffit archive file listed, 
  1399. .I unsit
  1400. extracts the files in the archive into separate files.
  1401. This makes it possible, for example, to separate a large StuffIt file
  1402. into component files for selective downloading, rather than
  1403. downloading the larger archive file just to extract a single, small
  1404. file.  It also allows the use of StuffIt to compress a group of files
  1405. into a single, smaller archive that can be uploaded to a Unix system
  1406. for storage, printing, etc.
  1407. .PP
  1408. In the normal mode, both the data and the resource forks of the
  1409. component Macintosh files in the archive are extracted and stored in
  1410. Unix files with the extension
  1411. .I .data
  1412. and 
  1413. .I .rsrc
  1414. appended to the end of the Macintosh file name.
  1415. In addition, a 
  1416. .I .info
  1417. file will be created with the Finder information.
  1418. These three file are compatible with the
  1419. .I macput
  1420. program for downloading to a Mac running Macterminal.
  1421. If only the data or resource fork is extracted, no addition extension is
  1422. appended to the Mac file name.
  1423. Characters in the Mac file name that are illegal (or unwieldy, like spaces)
  1424. are changed to underscores in the Unix file name.  The true Mac file name 
  1425. is retained in the
  1426. .I .info
  1427. file and is restored when the file is downloaded.
  1428. .PP
  1429. StuffIt version 1.5 has the ability to archive a group of files and folders
  1430. in such a way that the hierarchical relationship of the files and folders
  1431. is maintained.
  1432. .I Unsit
  1433. version 1.5 can unpack files archived in this manner and place them in
  1434. corresponding subdirectories so as to maintain the hierarchy.  As an option,
  1435. the hierarcy can be flattened out and all the files stored in the current
  1436. directory.
  1437. .PP
  1438. The options are similar to those for 
  1439. .I macput
  1440. and
  1441. .I unpit.
  1442. .TP
  1443. .B \-f
  1444. For StuffIt files containing a "Hierarchy Maintained Folder" entry, extract the
  1445. files into a "flat" organization (all in the current directory) rather than
  1446. maintaining the hierarchy by creating new directories, etc.
  1447. Default is to maintain the hierarchical folder organization.
  1448. .TP
  1449. .B \-l
  1450. List the files in the archive but do not extract them.  The name, size,
  1451. type, and creator of each file is listed.
  1452. .TP
  1453. .B \-m
  1454. Assumes the input file in MacBinary format rather than macput/macget
  1455. format and skips over the MacBinary header.
  1456. .TP
  1457. .B \-r
  1458. Extract resources forks only.
  1459. .TP
  1460. .B \-d
  1461. Extract data forks only.
  1462. .TP
  1463. .B \-u
  1464. Extract data fork and change into a Unix text file.
  1465. This only works if the file is really a text file.
  1466. .TP
  1467. .B \-q
  1468. Query user before extracting files and folders.  If a "n" answer is given for
  1469. a folder, none of the files or folders in that folder will be extracted.
  1470. .TP
  1471. .B \-v
  1472. Verbose option.  Causes 
  1473. .I unsit
  1474. to list name, size, type, and creator of each file extracted.
  1475. .SH BUGS
  1476. Files that were compressed by StuffIt with the Lempel-Ziv method and are
  1477. extracted with the 
  1478. .B \-u
  1479. switch (text files) are not checked for a correct CRC value when 
  1480. .I unsit
  1481. uncompresses them.  This is because 
  1482. .I unsit
  1483. pipes the data through
  1484. .I compress
  1485. and
  1486. .I tr
  1487. to extract the file and never has a chance to do the CRC check.
  1488. .PP
  1489. The
  1490. .I compress
  1491. program has been observed to go into strange states when uncompressing a 
  1492. damaged file.  Often it will get stuck writing out bogus data until the
  1493. disk fills up.  Since 
  1494. .I unsit
  1495. sends data through 
  1496. .I compress,
  1497. the same problem could occur when extracting files from a damaged Stuffit
  1498. archive.
  1499. .SH FILES
  1500. For archives that have been compressed with the Lempel-Ziv method, the 
  1501. .I compress 
  1502. program must be present on the system and in the search path since 
  1503. .I unsit 
  1504. uses it for the uncompressing.
  1505. .I Compress
  1506. is available from the comp.sources.unix archives.
  1507. .SH AUTHOR
  1508. Allan G. Weber (weber%brand.usc.edu@oberon.usc.edu)
  1509. SHAR_EOF
  1510. fi # end of overwriting check
  1511. #    End of shell archive
  1512. exit 0
  1513.  
  1514.  
  1515.